Modifying original code

Original file: Fig3_4_6_ExtFig5-6-10_RPM_RPMA_Allos_CellTag.R

This notebook is modified from the original code to remove the preprocessing steps and show figures inline within the notebook.

There is a separate notebook for the CellTag analysis.

Load the Seurat object and CellTag clones

TBO_seurat<-readRDS("../data/07_2025_RPM_RPMA_TBO_CellTag_Seurat_wSigs_FA_dpt_final.rds")
TBO_seurat
An object of class Seurat 
110982 features across 26618 samples within 2 assays 
Active assay: RNA (55491 features, 0 variable features)
 2 layers present: counts, data
 1 other assay present: norm
 2 dimensional reductions calculated: umap, fa
clones <- readRDS("../data/05_2025_RPM_RPMA_TBOAllo_CellTagClones_Onlyclones.rds")
clones
An object of class Seurat 
110982 features across 5965 samples within 2 assays 
Active assay: RNA (55491 features, 0 variable features)
 2 layers present: counts, data
 1 other assay present: norm
 2 dimensional reductions calculated: umap, fa

Load organoid data as SingleCellExperiment

sce <- as.SingleCellExperiment(TBO_seurat, assay = "norm")
Warning :The `slot` argument of `GetAssayData()` is deprecated as of SeuratObject 5.0.0.
ℹ Please use the `layer` argument instead.
ℹ The deprecated feature was likely used in the Seurat package.
  Please report the issue at <]8;;https://github.com/satijalab/seurat/issueshttps://github.com/satijalab/seurat/issues]8;;>.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_]8;;ide:run:warnings()warnings()]8;;` to see where this warning was generated.
phenotypes <- as.character(unique(sce@colData@listData$Pheno))
pheno_pairs_list <- combn(phenotypes, 2, simplify = FALSE)

Define color palettes

my_colors <- c(
  "#E41A1C", # strong red
  "#377EB8", # medium blue
  "#4DAF4A", # green
  "#984EA3", # purple
  "#FF7F00", # orange
  "#FFFF33", # yellow
  "#A65628", # brown
  "#e7298a", # pink
  "#666666", # grey
  "#66C2A5", # teal
  "#FC8D62", # salmon
  "#8DA0CB", # soft blue
  "#E78AC3", # soft pink (different from 8)
  "#A6D854", # light green (but yellowish tint, not green)
  "#FFD92F", # lemon yellow
  "#E5C494", # light brown
  "#B3B3B3", # light grey
  "#1B9E77", # deep teal
  "#D95F02", # dark orange
  "#7570B3", # strong purple
  "#66A61E"  # olive green (NOT same green as before)
)

Define function to plot violin plots by phenotype

Copied from 02_WT_RPM_Organoids_Allografts_notebook.Rmd

Needs SingleCellExperiment sce object and pheno_pairs_list defined in the notebook.

plotVlnByPhen <- function(feature, yl=c(-0.1,0.3), focus=NA) {
    if(!is.na(focus)) {
        pheno_pairs_list <- pheno_pairs_list[sapply(pheno_pairs_list, function(x) focus %in% x)]
    }
    
    scater::plotColData(sce, x = "Pheno", y = feature, colour_by = "Pheno") + 
        scale_discrete_manual(aesthetics = c("colour", "fill"), values=pheno_col) +
        theme(axis.title.y = element_text(size = 24), axis.text.y = element_text(size = 16),
              axis.text.x = element_blank(),   # rotate x-axis labels
              plot.title = element_blank(),    # remove plot title
              legend.position = "none"         # remove legend
        ) + labs(x = "",                     # custom x-axis title
                 y = "Signature score"        # custom y-axis title
        ) + ylim(yl[1], yl[2]) + 
        geom_boxplot(fill=pheno_col, alpha=1/5, position = position_dodge(width = .2),
                     size=0.2, color="black", notch=TRUE, notchwidth=0.3, outlier.shape = 2, outlier.colour=NA) # + 
        # stat_summary(fun = mean,
        #              geom = "point",
        #              shape = 18,
        #              size = 2,
        #              color = "red",
        #              position = position_dodge(width = 0.5)) + 
        # ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif", size=4, 
        #                            vjust = 0.5,
        #                            hide.ns = TRUE, comparisons = pheno_pairs_list)
}

Fig. 2e UMAP

DimPlot(TBO_seurat, group.by='Genotype', cols=c("darkorchid4","orange"),
        pt.size = 0.1,
        reduction='umap', label=FALSE, label.size=7, shuffle=TRUE) & NoAxes()

Fig. 2f (UMAP by Leiden cluster)

DimPlot(TBO_seurat, group.by='leiden_scVI_1.2', 
        cols=my_colors, reduction='umap', label=TRUE, label.size=5,
        pt.size = 0.1) & NoAxes() +
    theme(legend.position="none")

Idents(TBO_seurat) <- 'leiden_scVI_1.2'

x <- table(TBO_seurat@meta.data$Genotype,Idents(TBO_seurat))
proportions <- as.data.frame(100*prop.table(x, margin = 1))

colnames(proportions) <- c("Sample", "Cluster", "Frequency")

# ggpubr::ggbarplot(proportions, x="Sample", y="Frequency", fill = "Sample", group = "Sample",
#                   ylab = "Frequency (percent)", xlab="Phase", palette =c("indianred3","green3","royalblue4")) +
#     theme_bw() + facet_wrap(facets = "Cluster", scales="free_y", ncol =4) +
#     theme(axis.text.y = element_text(size=6)) + ggpubr::rotate_x_text(angle = 45)

Fig 2f

# Stacked
p <- ggplot(proportions, aes(fill=Cluster, y=Frequency, x=Sample)) + 
    geom_bar(position="stack", stat="identity")

p + scale_fill_manual(values=my_colors) + theme_bw() + 
    theme(axis.text.y = element_text(size=16), 
          axis.text.x = element_text(size=16, angle = 90, vjust = 0.5, hjust=1), 
          axis.title.x = element_text(size=16), axis.title.y = element_text(size=16), 
          legend.text = element_text(size=12), legend.title = element_blank()) + 
    labs(x = NULL, y = "Sample composition (%)")

Fig. 2h

UMAP colored by SCLC fate

# Define fate color vector and use to plot by cell state
pheno_col <- c("brown2","darkorchid4","dodgerblue","#66A61E","orange","turquoise4","turquoise")
DimPlot(TBO_seurat, group.by='Pheno', cols=pheno_col, reduction='umap', label=FALSE, 
        shuffle=TRUE, label.size=6) & NoAxes()

Fig. 2h (stacked barplot by Pheno)

Idents(TBO_seurat) <-'Pheno'

x <- table(TBO_seurat@meta.data$Genotype,Idents(TBO_seurat))
proportions <- as.data.frame(100*prop.table(x, margin = 1))

colnames(proportions)<-c("Cluster", "Sample", "Frequency")

p <- ggplot(proportions, aes(fill=Sample, y=Frequency, x=Cluster)) + 
    geom_bar(position="stack", stat="identity")

p + scale_fill_manual(values=pheno_col) + theme_bw() + 
    theme(axis.text.y = element_text(size=20), 
          axis.text.x=element_text(size=20, angle = 90, hjust = 1, vjust = 0.5), 
          axis.title.x = element_text(size=20), axis.title.y = element_text(size=20), 
          legend.text = element_text(size=20), legend.title = element_text(size=20)) + 
    labs(x = NULL)

Fig. 2i UMAP

NE score (correlation)

FeaturePlot(TBO_seurat, features = c("NE_spearman"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig 2i (violin plots of NE score by SCLC fate)

plotVlnByPhen("NE_spearman", yl=c(-.7, .8))

Fig 2i (violin plots of NE score by genotype)

x <- scater::plotColData(sce, x = "Genotype", y = "NE_spearman", colour_by = "Genotype") + 
    scale_discrete_manual(aesthetics = c("colour", "fill"), values=c("darkorchid4","orange"))

x <- x + theme(axis.title.y = element_text(size = 24),axis.text.y = element_text(size = 16), 
               axis.text.x = element_blank(), 
               # plot.title = element_blank(),
               legend.position = "none") + labs(x = "",  y = "Signature score") +  ylim(-1,1) + 
    geom_boxplot(fill=c("darkorchid4","orange"), alpha=1/5, 
                 position = position_dodge(width = .2), size=0.2,
                 color="black", notch=TRUE, notchwidth=0.3, outlier.shape = 2, outlier.colour=NA)

## Perform wilcoxon rank-sum test for RPM vs RPMA on the NE score data (Fig. 3i) ##
x + stat_summary(fun = mean,
                 geom = "point",
                 shape = 18,
                 size = 2,
                 color = "red",
                 position = position_dodge(width = 0.9)) + 
    ggpubr::stat_compare_means(method = "wilcox.test",label = "p.signif", 
                               hide.ns = TRUE,comparisons = list(c("RPM", "RPMA")))

Fig. 2j

Fig 2j (UMAP marker gene expression)

Equivalent color schemes:
* viridis::scale_color_viridis(option="rocket", direction=-1)
* scale_color_gradientn(colors=viridis::rocket(10, direction=-1))

# TF target gene scores in UMAP
FeaturePlot(TBO_seurat, features = c("ASCL1_Targets1"), pt.size=0.2, 
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("NEUROD1_Targets1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("ATOH1_Targets1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("POU2F3_Targets1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("YAP_Activity1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

VlnPlots by genotype with wilcoxon rank sum tests

Fig. 2j (violin plots)

plotTFscoresVln <- function(score_name, yl=c(-.1, .32)) {
    a <- VlnPlot(TBO_seurat,
                 features = c(score_name),
                 group.by = "Genotype",
                 cols = c("darkorchid4", "orange"),
                 pt.size = 0.01,
                 alpha = 0.05,
                 ncol = 1) + 
        theme(axis.title.y = element_text(size = 20),
              axis.text.x = element_text(angle = 0, hjust = 0.5, size=20),  # rotate x-axis labels
              # plot.title = element_blank(),                                 # remove plot title
              legend.position = "none"                                      # remove legend
        ) + 
        labs(x = "",             # custom x-axis title
             y = "Expression"  # custom y-axis title
        ) + ylim(yl[1], yl[2]) + 
        stat_summary(fun = mean,
                     geom = "point",
                     shape = 18,
                     size = 2,
                     color = "red",
                     position = position_dodge(width = 0.9)) + 
        ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif", size=8, 
                                   hide.ns = TRUE, comparisons = list(c("RPM", "RPMA")))
        
        # Add mean point and do wilcoxon rank sum test 
    return(a)
}

Fig 2j (insets)

plotTFscoresVln("ATOH1_Targets1")

plotTFscoresVln("ASCL1_Targets1", yl=c(-0.1, 0.8))

plotTFscoresVln("NEUROD1_Targets1")

plotTFscoresVln("POU2F3_Targets1")

plotTFscoresVln("YAP_Activity1", yl=c(-0.1, 1))

Fig. 2k (UMAP by cell type consensus signature)

FeaturePlot(TBO_seurat, features = c("NE_Consensus1"), pt.size=0.2, 
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Basal_Consensus1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Tuft_Consensus1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig. 2k (violin plots of consensus signatures by SCLC fate)

plotVlnByPhen("NE_Consensus1", yl=c(-0.5, 1.3))

plotVlnByPhen("Tuft_Consensus1", yl=c(-0.25, 1))

plotVlnByPhen("Basal_Consensus1", yl=c(-0.1, 1.1))

Fig 2l (violin plots of SCLC arhcetype scores by phenotype)

plotVlnByPhen("A_Archetype1", yl=c(-0.05, 0.27))

plotVlnByPhen("A2_Archetype1", yl=c(-0.05, 0.2))

plotVlnByPhen("N_Archetype1", yl=c(0, 0.3))

plotVlnByPhen("P_Archetype1", yl=c(0, 0.27))

Ext Data Fig 5c

plotStackedBarByGeno <- function(gene, lab) {
    dat <- FetchData(TBO_seurat, vars = c(gene, "Genotype"))
    dat <- dat %>%
      mutate(Expression_Status = ifelse(dat[,gene] > 0.01, "Positive", "Negative"))
    
    x <- table(dat$Genotype, dat$Expression_Status)
    
    proportions <- as.data.frame(prop.table(x, margin = 1))
    colnames(proportions) <- c("Cluster", "Sample", "Fraction")

    p <- ggplot(proportions, aes(fill = Sample, y = Fraction, x = Cluster)) + 
        geom_bar(position = "stack", stat = "identity")
    p <- p + scale_fill_manual(values=c("blue4","red3"))+ theme_bw() + 
        theme(axis.text.y = element_text(size=20), axis.text.x=element_text(size=20), 
              axis.title.x =element_text(size=20), axis.title.y = element_text(size=20), 
              legend.text = element_text(size=20), legend.title = element_text(size=0), 
              plot.title = element_text(size = 18, face = "plain", hjust = 0.5)) + 
        labs(y = lab, x = NULL)
    return(p)
}
plotStackedBarByGeno("Ascl1", "Fraction of Ascl1-hi cells (>0.01)")

plotStackedBarByGeno("Neurod1", "Fraction of Neurod1-hi cells (>0.01)")

plotStackedBarByGeno("Pou2f3", "Fraction of Pou2f3-hi cells (>0.01)")

Extended Data Fig. 5e

Violin plots of expression of TFs by Leiden cluster

genes <- c("Ascl1","Neurod1","Pou2f3")

# Create violin plots with Kruskal-Wallis test
plots <- lapply(genes, function(gene) {
  p <- VlnPlot(TBO_seurat,
               features = gene,
               group.by = "leiden_scVI_1.2",
               cols = my_colors,
               alpha = 0.5) +  # smaller dots
    ggpubr::stat_compare_means(method = "kruskal.test", 
                       label = "p.format", 
                       label.x = 2,size = 5) +
    ggtitle("") +
    theme(plot.title = element_text(face = "italic"), legend.position = "none",  # Remove legend
          axis.title.x = element_blank(),axis.title.y = element_text(size = 20),
          axis.text.y = element_text(size = 20), axis.text.x = element_text(size = 14)) +  # Remove x-axis label
    labs(y = "Expression")  # Change y-axis label to "Expression"
  return(p)
})

# Arrange plots
patchwork::wrap_plots(plots, ncol = 3)

Ext Data Fig 10

FeaturePlot(TBO_seurat, features = c("Iono_Mouse_Ext1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

FeaturePlot(TBO_seurat, features = c("Iono_Human1"), pt.size=0.2,
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Ext Data Fig. 10e (violin plots of consensus signatures by SCLC fate)

plotVlnByPhen("Iono_Mouse_Ext1", yl=c(-0.1, 0.45))

plotVlnByPhen("Iono_Human1", yl=c(-0.1, .75))

Fig 5d

Caris SCLC tumor signatures in basal cells

caris_feat <-  c("Caris_A1","Caris_Y1","Caris_N1","Caris_Mixed1","Caris_P1","Caris_TN-1")
library(viridis)
v <- FeaturePlot(TBO_seurat, features = caris_feat, pt.size=0.2, reduction='umap') 
v <- lapply(v, `+`, scale_color_viridis(option="rocket", direction=-1))
lapply(v, `+`, NoAxes())
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Fig 5d (violin plots of human tumor SCLC scores by SCLC fate)

plotVlnByPhen("Caris_A1", yl=c(-0.1, 0.2))

plotVlnByPhen("Caris_Y1", yl=c(-0.1, 0.2))

plotVlnByPhen("Caris_N1", yl=c(-0.1, 0.3))

plotVlnByPhen("Caris_Mixed1", yl=c(-0.1, 0.15))

plotVlnByPhen("Caris_P1", yl=c(-0.1, 0.25))

plotVlnByPhen("Caris_TN.1", yl=c(-0.1, 0.25))

Fig. 5e

Gene signature scores correlation heatmap

signature_matrix <- FetchData(TBO_seurat, vars = c("Caris_A1", "George_A1", "Liu_A1","Lissa_A1","ASCL1_Targets1",
                                                   "Caris_N1","George_N1", "Liu_N1","Lissa_N1", "NEUROD1_Targets1",
                                                   "Caris_P1","George_P1", "Liu_P1","POU2F3_Targets1",
                                                   "Caris_Y1","George_Y1", "Lissa_Y1", "YAP_Activity1",
                                                   "T_Cell_Inflamed_Gay1","MHC_Sig_Gay1",
                                                   "NE_Consensus1","Basal_Consensus1","Tuft_Consensus1"))

# Compute Pearson correlation matrix
correlation_matrix <- cor(signature_matrix, method = "pearson")

# Define color scale from -1 to 1
breaks_seq <- seq(-1, 1, length.out = 100)  # Ensure scale covers full correlation range

pheatmap::pheatmap(correlation_matrix, 
         color = scico::scico(100, palette = "berlin"),
         display_numbers = FALSE, 
         breaks = breaks_seq, number_color = "gray80",fontsize_number=6,
         main = "Signature correlation in mouse TBO Allografts", cluster_cols = TRUE, cluster_rows=TRUE)

Fig 5g

Inflammatory signatures in basal cells

# Fig 5g feature plot (MHC_Sig_Gay1="Antigen presentation") #
FeaturePlot(TBO_seurat, features = c("MHC_Sig_Gay1"), pt.size=0.2, 
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()


### NMF3-I signature for Fig. 5g
FeaturePlot(TBO_seurat, features = c("NMF3-I1"), pt.size=0.2, 
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()


### Gay et al SCLC-I signature for Fig. 5g
FeaturePlot(TBO_seurat, features = c("Gay_SCLC-I1"), pt.size=0.2, 
            reduction='umap') + viridis::scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Fig 5g (violin plots of inflammation scores by SCLC fate)

plotVlnByPhen("MHC_Sig_Gay1", yl=c(-0.1, 0.8))

plotVlnByPhen("NMF3.I1", yl=c(-0.1, 0.5))

plotVlnByPhen("Gay_SCLC.I1", yl=c(-0.1, 0.3))

Fig 5h (violin plots of therapeutic target gene expression by SCLC fate)

x_labs <- c("A","A/N","N","At","P","SL","B")

v <- VlnPlot(TBO_seurat, features = c("Dll3", "Ncam1", "Sez6", "Tacstd2"), 
        group.by=c("Pheno"), cols=pheno_col,alpha=0.05, ncol=4)
v <- lapply(v,  `+`, labs(x=NULL, y="Expression"))
v <- lapply(v,  `+`, theme(axis.text.x = element_text(angle=90)))
v <- lapply(v,  `+`,  scale_x_discrete(labels=x_labs))

patchwork::wrap_plots(v, ncol=4)

Ext Data Fig 6a

DimPlot(TBO_seurat, group.by='GenoCT', cols=my_colors, shuffle=TRUE, 
        reduction='umap', label=FALSE, label.size=6) & NoAxes() + NoLegend()

DimPlot(TBO_seurat, group.by='GenoCT', cols=my_colors, shuffle=TRUE, 
        reduction='fa', label=FALSE, label.size=6) & NoAxes() + NoLegend()

CellTag analysis in other notebook

LS0tCnRpdGxlOiAiUlBNIFJQTUEgQWxsb3Mgbm90ZWJvb2siCmF1dGhvcjogIkFiYmllIElyZWxhbmQsIERhcnJlbiBUeXNvbiIKZGF0ZTogIjIwMjUtMDYtMjQiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIyBNb2RpZnlpbmcgb3JpZ2luYWwgY29kZQoKT3JpZ2luYWwgZmlsZTogW0ZpZzNfNF82X0V4dEZpZzUtNi0xMF9SUE1fUlBNQV9BbGxvc19DZWxsVGFnLlJdKFByZXByb2Nlc3NpbmdfZm9yX3JlZmVyZW5jZS9SX0NvZGUvRmlnM180XzZfRXh0RmlnNS02LTEwX1JQTV9SUE1BX0FsbG9zX0NlbGxUYWcuUikKClRoaXMgbm90ZWJvb2sgaXMgbW9kaWZpZWQgZnJvbSB0aGUgb3JpZ2luYWwgY29kZSB0byByZW1vdmUgdGhlIHByZXByb2Nlc3Npbmcgc3RlcHMgYW5kIHNob3cgZmlndXJlcyBpbmxpbmUgd2l0aGluIHRoZSBub3RlYm9vay4KClRoZXJlIGlzIGEgW3NlcGFyYXRlIG5vdGVib29rIGZvciB0aGUgQ2VsbFRhZyBhbmFseXNpc10oMDRfUlBNX1JQTUFfQWxsb3NfQ2VsbFRhZ19ub3RlYm9vay5uYi5odG1sKS4gIAoKIyMjIFJlbGF0ZWQgdG86CgotICAgRmlnIDJlLWwKLSAgIEZpZyA1ZC1oCi0gICBFeHRlbmRlZCBEYXRhIEZpZyA1YyxlCi0gICBFeHRlbmRlZCBEYXRhIEZpZyA2YQotICAgRXh0ZW5kZWQgRGF0YSBGaWcgMTBlCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICAgIGxpYnJhcnkoU2V1cmF0KQogICAgbGlicmFyeShTZXVyYXRPYmplY3QpCiAgICBsaWJyYXJ5KFN1bW1hcml6ZWRFeHBlcmltZW50KQogICAgbGlicmFyeShnZ3Bsb3QyKQogICAgbGlicmFyeShnZ3B1YnIpCn0pCmBgYAoKIyMjIExvYWQgdGhlIFNldXJhdCBvYmplY3QgYW5kIENlbGxUYWcgY2xvbmVzCgpgYGB7cn0KVEJPX3NldXJhdDwtcmVhZFJEUygiLi4vZGF0YS8wN18yMDI1X1JQTV9SUE1BX1RCT19DZWxsVGFnX1NldXJhdF93U2lnc19GQV9kcHRfZmluYWwucmRzIikKVEJPX3NldXJhdAoKY2xvbmVzIDwtIHJlYWRSRFMoIi4uL2RhdGEvMDVfMjAyNV9SUE1fUlBNQV9UQk9BbGxvX0NlbGxUYWdDbG9uZXNfT25seWNsb25lcy5yZHMiKQpjbG9uZXMKYGBgCgojIyMgTG9hZCBvcmdhbm9pZCBkYXRhIGFzIFNpbmdsZUNlbGxFeHBlcmltZW50CgpgYGB7cn0Kc2NlIDwtIGFzLlNpbmdsZUNlbGxFeHBlcmltZW50KFRCT19zZXVyYXQsIGFzc2F5ID0gIm5vcm0iKQpgYGAKCmBgYHtyfQpwaGVub3R5cGVzIDwtIGFzLmNoYXJhY3Rlcih1bmlxdWUoc2NlQGNvbERhdGFAbGlzdERhdGEkUGhlbm8pKQpwaGVub19wYWlyc19saXN0IDwtIGNvbWJuKHBoZW5vdHlwZXMsIDIsIHNpbXBsaWZ5ID0gRkFMU0UpCmBgYAoKIyMjIERlZmluZSBjb2xvciBwYWxldHRlcwoKYGBge3J9Cm15X2NvbG9ycyA8LSBjKAogICIjRTQxQTFDIiwgIyBzdHJvbmcgcmVkCiAgIiMzNzdFQjgiLCAjIG1lZGl1bSBibHVlCiAgIiM0REFGNEEiLCAjIGdyZWVuCiAgIiM5ODRFQTMiLCAjIHB1cnBsZQogICIjRkY3RjAwIiwgIyBvcmFuZ2UKICAiI0ZGRkYzMyIsICMgeWVsbG93CiAgIiNBNjU2MjgiLCAjIGJyb3duCiAgIiNlNzI5OGEiLCAjIHBpbmsKICAiIzY2NjY2NiIsICMgZ3JleQogICIjNjZDMkE1IiwgIyB0ZWFsCiAgIiNGQzhENjIiLCAjIHNhbG1vbgogICIjOERBMENCIiwgIyBzb2Z0IGJsdWUKICAiI0U3OEFDMyIsICMgc29mdCBwaW5rIChkaWZmZXJlbnQgZnJvbSA4KQogICIjQTZEODU0IiwgIyBsaWdodCBncmVlbiAoYnV0IHllbGxvd2lzaCB0aW50LCBub3QgZ3JlZW4pCiAgIiNGRkQ5MkYiLCAjIGxlbW9uIHllbGxvdwogICIjRTVDNDk0IiwgIyBsaWdodCBicm93bgogICIjQjNCM0IzIiwgIyBsaWdodCBncmV5CiAgIiMxQjlFNzciLCAjIGRlZXAgdGVhbAogICIjRDk1RjAyIiwgIyBkYXJrIG9yYW5nZQogICIjNzU3MEIzIiwgIyBzdHJvbmcgcHVycGxlCiAgIiM2NkE2MUUiICAjIG9saXZlIGdyZWVuIChOT1Qgc2FtZSBncmVlbiBhcyBiZWZvcmUpCikKCmBgYAoKIyMjIyBEZWZpbmUgZnVuY3Rpb24gdG8gcGxvdCB2aW9saW4gcGxvdHMgYnkgcGhlbm90eXBlCgpDb3BpZWQgZnJvbSBbMDJfV1RfUlBNX09yZ2Fub2lkc19BbGxvZ3JhZnRzX25vdGVib29rLlJtZF0oMDJfV1RfUlBNX09yZ2Fub2lkc19BbGxvZ3JhZnRzX25vdGVib29rLlJtZCkKCk5lZWRzIFNpbmdsZUNlbGxFeHBlcmltZW50IGBzY2VgIG9iamVjdCBhbmQgYHBoZW5vX3BhaXJzX2xpc3RgIGRlZmluZWQgaW4gdGhlIG5vdGVib29rLgoKYGBge3J9CnBsb3RWbG5CeVBoZW4gPC0gZnVuY3Rpb24oZmVhdHVyZSwgeWw9YygtMC4xLDAuMyksIGZvY3VzPU5BKSB7CiAgICBpZighaXMubmEoZm9jdXMpKSB7CiAgICAgICAgcGhlbm9fcGFpcnNfbGlzdCA8LSBwaGVub19wYWlyc19saXN0W3NhcHBseShwaGVub19wYWlyc19saXN0LCBmdW5jdGlvbih4KSBmb2N1cyAlaW4lIHgpXQogICAgfQogICAgCiAgICBzY2F0ZXI6OnBsb3RDb2xEYXRhKHNjZSwgeCA9ICJQaGVubyIsIHkgPSBmZWF0dXJlLCBjb2xvdXJfYnkgPSAiUGhlbm8iKSArIAogICAgICAgIHNjYWxlX2Rpc2NyZXRlX21hbnVhbChhZXN0aGV0aWNzID0gYygiY29sb3VyIiwgImZpbGwiKSwgdmFsdWVzPXBoZW5vX2NvbCkgKwogICAgICAgIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCAgICMgcm90YXRlIHgtYXhpcyBsYWJlbHMKICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAgICAjIHJlbW92ZSBwbG90IHRpdGxlCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiICAgICAgICAgIyByZW1vdmUgbGVnZW5kCiAgICAgICAgKSArIGxhYnMoeCA9ICIiLCAgICAgICAgICAgICAgICAgICAgICMgY3VzdG9tIHgtYXhpcyB0aXRsZQogICAgICAgICAgICAgICAgIHkgPSAiU2lnbmF0dXJlIHNjb3JlIiAgICAgICAgIyBjdXN0b20geS1heGlzIHRpdGxlCiAgICAgICAgKSArIHlsaW0oeWxbMV0sIHlsWzJdKSArIAogICAgICAgIGdlb21fYm94cGxvdChmaWxsPXBoZW5vX2NvbCwgYWxwaGE9MS81LCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjIpLAogICAgICAgICAgICAgICAgICAgICBzaXplPTAuMiwgY29sb3I9ImJsYWNrIiwgbm90Y2g9VFJVRSwgbm90Y2h3aWR0aD0wLjMsIG91dGxpZXIuc2hhcGUgPSAyLCBvdXRsaWVyLmNvbG91cj1OQSkgIyArIAogICAgICAgICMgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sCiAgICAgICAgIyAgICAgICAgICAgICAgZ2VvbSA9ICJwb2ludCIsCiAgICAgICAgIyAgICAgICAgICAgICAgc2hhcGUgPSAxOCwKICAgICAgICAjICAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAjICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgICMgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArIAogICAgICAgICMgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gIndpbGNveC50ZXN0IiwgbGFiZWwgPSAicC5zaWduaWYiLCBzaXplPTQsIAogICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAwLjUsCiAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRlLm5zID0gVFJVRSwgY29tcGFyaXNvbnMgPSBwaGVub19wYWlyc19saXN0KQp9CmBgYAoKIyMjIEZpZy4gMmUgVU1BUAoKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRGltUGxvdChUQk9fc2V1cmF0LCBncm91cC5ieT0nR2Vub3R5cGUnLCBjb2xzPWMoImRhcmtvcmNoaWQ0Iiwib3JhbmdlIiksCiAgICAgICAgcHQuc2l6ZSA9IDAuMSwKICAgICAgICByZWR1Y3Rpb249J3VtYXAnLCBsYWJlbD1GQUxTRSwgbGFiZWwuc2l6ZT03LCBzaHVmZmxlPVRSVUUpICYgTm9BeGVzKCkKCmBgYAoKIyMjIEZpZy4gMmYgKFVNQVAgYnkgTGVpZGVuIGNsdXN0ZXIpCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpEaW1QbG90KFRCT19zZXVyYXQsIGdyb3VwLmJ5PSdsZWlkZW5fc2NWSV8xLjInLCAKICAgICAgICBjb2xzPW15X2NvbG9ycywgcmVkdWN0aW9uPSd1bWFwJywgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT01LAogICAgICAgIHB0LnNpemUgPSAwLjEpICYgTm9BeGVzKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmBgYAoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CklkZW50cyhUQk9fc2V1cmF0KSA8LSAnbGVpZGVuX3NjVklfMS4yJwoKeCA8LSB0YWJsZShUQk9fc2V1cmF0QG1ldGEuZGF0YSRHZW5vdHlwZSxJZGVudHMoVEJPX3NldXJhdCkpCnByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUoMTAwKnByb3AudGFibGUoeCwgbWFyZ2luID0gMSkpCgpjb2xuYW1lcyhwcm9wb3J0aW9ucykgPC0gYygiU2FtcGxlIiwgIkNsdXN0ZXIiLCAiRnJlcXVlbmN5IikKCiMgZ2dwdWJyOjpnZ2JhcnBsb3QocHJvcG9ydGlvbnMsIHg9IlNhbXBsZSIsIHk9IkZyZXF1ZW5jeSIsIGZpbGwgPSAiU2FtcGxlIiwgZ3JvdXAgPSAiU2FtcGxlIiwKIyAgICAgICAgICAgICAgICAgICB5bGFiID0gIkZyZXF1ZW5jeSAocGVyY2VudCkiLCB4bGFiPSJQaGFzZSIsIHBhbGV0dGUgPWMoImluZGlhbnJlZDMiLCJncmVlbjMiLCJyb3lhbGJsdWU0IikpICsKIyAgICAgdGhlbWVfYncoKSArIGZhY2V0X3dyYXAoZmFjZXRzID0gIkNsdXN0ZXIiLCBzY2FsZXM9ImZyZWVfeSIsIG5jb2wgPTQpICsKIyAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT02KSkgKyBnZ3B1YnI6OnJvdGF0ZV94X3RleHQoYW5nbGUgPSA0NSkKYGBgCgojIyMjIEZpZyAyZgoKYGBge3IgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD0zLjUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgU3RhY2tlZApwIDwtIGdncGxvdChwcm9wb3J0aW9ucywgYWVzKGZpbGw9Q2x1c3RlciwgeT1GcmVxdWVuY3ksIHg9U2FtcGxlKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikKCnAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9bXlfY29sb3JzKSArIHRoZW1lX2J3KCkgKyAKICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwgCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArIAogICAgbGFicyh4ID0gTlVMTCwgeSA9ICJTYW1wbGUgY29tcG9zaXRpb24gKCUpIikKYGBgCgojIyMgRmlnLiAyaAoKVU1BUCBjb2xvcmVkIGJ5IFNDTEMgZmF0ZQoKYGBge3IgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBEZWZpbmUgZmF0ZSBjb2xvciB2ZWN0b3IgYW5kIHVzZSB0byBwbG90IGJ5IGNlbGwgc3RhdGUKcGhlbm9fY29sIDwtIGMoImJyb3duMiIsImRhcmtvcmNoaWQ0IiwiZG9kZ2VyYmx1ZSIsIiM2NkE2MUUiLCJvcmFuZ2UiLCJ0dXJxdW9pc2U0IiwidHVycXVvaXNlIikKRGltUGxvdChUQk9fc2V1cmF0LCBncm91cC5ieT0nUGhlbm8nLCBjb2xzPXBoZW5vX2NvbCwgcmVkdWN0aW9uPSd1bWFwJywgbGFiZWw9RkFMU0UsIAogICAgICAgIHNodWZmbGU9VFJVRSwgbGFiZWwuc2l6ZT02KSAmIE5vQXhlcygpCgpgYGAKCiMjIyMgRmlnLiAyaCAoc3RhY2tlZCBiYXJwbG90IGJ5IFBoZW5vKQoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KSWRlbnRzKFRCT19zZXVyYXQpIDwtJ1BoZW5vJwoKeCA8LSB0YWJsZShUQk9fc2V1cmF0QG1ldGEuZGF0YSRHZW5vdHlwZSxJZGVudHMoVEJPX3NldXJhdCkpCnByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUoMTAwKnByb3AudGFibGUoeCwgbWFyZ2luID0gMSkpCgpjb2xuYW1lcyhwcm9wb3J0aW9ucyk8LWMoIkNsdXN0ZXIiLCAiU2FtcGxlIiwgIkZyZXF1ZW5jeSIpCgpwIDwtIGdncGxvdChwcm9wb3J0aW9ucywgYWVzKGZpbGw9U2FtcGxlLCB5PUZyZXF1ZW5jeSwgeD1DbHVzdGVyKSkgKyAKICAgIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikKCnAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9cGhlbm9fY29sKSArIHRoZW1lX2J3KCkgKyAKICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCAKICAgICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTIwLCBhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41KSwgCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MjApKSArIAogICAgbGFicyh4ID0gTlVMTCkKYGBgCgojIyMjIEZpZy4gMmkgVU1BUAoKTkUgc2NvcmUgKGNvcnJlbGF0aW9uKQoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9My41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIk5FX3NwZWFybWFuIiksIHB0LnNpemU9MC4yLAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQpgYGAKCiMjIyMgRmlnIDJpICh2aW9saW4gcGxvdHMgb2YgTkUgc2NvcmUgYnkgU0NMQyBmYXRlKQoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiTkVfc3BlYXJtYW4iLCB5bD1jKC0uNywgLjgpKQpgYGAKCiMjIyMgRmlnIDJpICh2aW9saW4gcGxvdHMgb2YgTkUgc2NvcmUgYnkgZ2Vub3R5cGUpCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0yLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp4IDwtIHNjYXRlcjo6cGxvdENvbERhdGEoc2NlLCB4ID0gIkdlbm90eXBlIiwgeSA9ICJORV9zcGVhcm1hbiIsIGNvbG91cl9ieSA9ICJHZW5vdHlwZSIpICsgCiAgICBzY2FsZV9kaXNjcmV0ZV9tYW51YWwoYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIiksIHZhbHVlcz1jKCJkYXJrb3JjaGlkNCIsIm9yYW5nZSIpKQoKeCA8LSB4ICsgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNCksYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwgCiAgICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICAgIyBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgbGFicyh4ID0gIiIsICB5ID0gIlNpZ25hdHVyZSBzY29yZSIpICsgIHlsaW0oLTEsMSkgKyAKICAgIGdlb21fYm94cGxvdChmaWxsPWMoImRhcmtvcmNoaWQ0Iiwib3JhbmdlIiksIGFscGhhPTEvNSwgCiAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IC4yKSwgc2l6ZT0wLjIsCiAgICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwgbm90Y2g9VFJVRSwgbm90Y2h3aWR0aD0wLjMsIG91dGxpZXIuc2hhcGUgPSAyLCBvdXRsaWVyLmNvbG91cj1OQSkKCiMjIFBlcmZvcm0gd2lsY294b24gcmFuay1zdW0gdGVzdCBmb3IgUlBNIHZzIFJQTUEgb24gdGhlIE5FIHNjb3JlIGRhdGEgKEZpZy4gM2kpICMjCnggKyBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwKICAgICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwKICAgICAgICAgICAgICAgICBzaGFwZSA9IDE4LAogICAgICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgICBnZ3B1YnI6OnN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGxhYmVsID0gInAuc2lnbmlmIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRlLm5zID0gVFJVRSxjb21wYXJpc29ucyA9IGxpc3QoYygiUlBNIiwgIlJQTUEiKSkpCgpgYGAKCiMjIyBGaWcuIDJqCgojIyMjIEZpZyAyaiAoVU1BUCBtYXJrZXIgZ2VuZSBleHByZXNzaW9uKQoKRXF1aXZhbGVudCBjb2xvciBzY2hlbWVzOlwKXCogYHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLCBkaXJlY3Rpb249LTEpYFwKXCogYHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnM9dmlyaWRpczo6cm9ja2V0KDEwLCBkaXJlY3Rpb249LTEpKWAKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgVEYgdGFyZ2V0IGdlbmUgc2NvcmVzIGluIFVNQVAKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJBU0NMMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwgCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiTkVVUk9EMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJBVE9IMV9UYXJnZXRzMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJQT1UyRjNfVGFyZ2V0czEiKSwgcHQuc2l6ZT0wLjIsCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcpICsgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsZGlyZWN0aW9uPS0xKSAmIE5vQXhlcygpCkZlYXR1cmVQbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiWUFQX0FjdGl2aXR5MSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKCmBgYAoKIyMjIFZsblBsb3RzIGJ5IGdlbm90eXBlIHdpdGggd2lsY294b24gcmFuayBzdW0gdGVzdHMKCiMjIyMgRmlnLiAyaiAodmlvbGluIHBsb3RzKQoKYGBge3J9CnBsb3RURnNjb3Jlc1ZsbiA8LSBmdW5jdGlvbihzY29yZV9uYW1lLCB5bD1jKC0uMSwgLjMyKSkgewogICAgYSA8LSBWbG5QbG90KFRCT19zZXVyYXQsCiAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBjKHNjb3JlX25hbWUpLAogICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICBjb2xzID0gYygiZGFya29yY2hpZDQiLCAib3JhbmdlIiksCiAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuMDEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjA1LAogICAgICAgICAgICAgICAgIG5jb2wgPSAxKSArIAogICAgICAgIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLAogICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAwLjUsIHNpemU9MjApLCAgIyByb3RhdGUgeC1heGlzIGxhYmVscwogICAgICAgICAgICAgICMgcGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlbW92ZSBwbG90IHRpdGxlCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlbW92ZSBsZWdlbmQKICAgICAgICApICsgCiAgICAgICAgbGFicyh4ID0gIiIsICAgICAgICAgICAgICMgY3VzdG9tIHgtYXhpcyB0aXRsZQogICAgICAgICAgICAgeSA9ICJFeHByZXNzaW9uIiAgIyBjdXN0b20geS1heGlzIHRpdGxlCiAgICAgICAgKSArIHlsaW0oeWxbMV0sIHlsWzJdKSArIAogICAgICAgIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwKICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpKSArIAogICAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ3aWxjb3gudGVzdCIsIGxhYmVsID0gInAuc2lnbmlmIiwgc2l6ZT04LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRlLm5zID0gVFJVRSwgY29tcGFyaXNvbnMgPSBsaXN0KGMoIlJQTSIsICJSUE1BIikpKQogICAgICAgIAogICAgICAgICMgQWRkIG1lYW4gcG9pbnQgYW5kIGRvIHdpbGNveG9uIHJhbmsgc3VtIHRlc3QgCiAgICByZXR1cm4oYSkKfQpgYGAKCiMjIyMgRmlnIDJqIChpbnNldHMpCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VEZzY29yZXNWbG4oIkFUT0gxX1RhcmdldHMxIikKcGxvdFRGc2NvcmVzVmxuKCJBU0NMMV9UYXJnZXRzMSIsIHlsPWMoLTAuMSwgMC44KSkKcGxvdFRGc2NvcmVzVmxuKCJORVVST0QxX1RhcmdldHMxIikKcGxvdFRGc2NvcmVzVmxuKCJQT1UyRjNfVGFyZ2V0czEiKQpwbG90VEZzY29yZXNWbG4oIllBUF9BY3Rpdml0eTEiLCB5bD1jKC0wLjEsIDEpKQpgYGAKCiMjIyBGaWcuIDJrIChVTUFQIGJ5IGNlbGwgdHlwZSBjb25zZW5zdXMgc2lnbmF0dXJlKQoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJORV9Db25zZW5zdXMxIiksIHB0LnNpemU9MC4yLCAKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJCYXNhbF9Db25zZW5zdXMxIiksIHB0LnNpemU9MC4yLAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIlR1ZnRfQ29uc2Vuc3VzMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKYGBgCgojIyMgRmlnLiAyayAodmlvbGluIHBsb3RzIG9mIGNvbnNlbnN1cyBzaWduYXR1cmVzIGJ5IFNDTEMgZmF0ZSkKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3RWbG5CeVBoZW4oIk5FX0NvbnNlbnN1czEiLCB5bD1jKC0wLjUsIDEuMykpCnBsb3RWbG5CeVBoZW4oIlR1ZnRfQ29uc2Vuc3VzMSIsIHlsPWMoLTAuMjUsIDEpKQpwbG90VmxuQnlQaGVuKCJCYXNhbF9Db25zZW5zdXMxIiwgeWw9YygtMC4xLCAxLjEpKQpgYGAKCiMjIyMgRmlnIDJsICh2aW9saW4gcGxvdHMgb2YgU0NMQyBhcmhjZXR5cGUgc2NvcmVzIGJ5IHBoZW5vdHlwZSkKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3RWbG5CeVBoZW4oIkFfQXJjaGV0eXBlMSIsIHlsPWMoLTAuMDUsIDAuMjcpKQpwbG90VmxuQnlQaGVuKCJBMl9BcmNoZXR5cGUxIiwgeWw9YygtMC4wNSwgMC4yKSkKcGxvdFZsbkJ5UGhlbigiTl9BcmNoZXR5cGUxIiwgeWw9YygwLCAwLjMpKQpwbG90VmxuQnlQaGVuKCJQX0FyY2hldHlwZTEiLCB5bD1jKDAsIDAuMjcpKQpgYGAKCiMjIyMgRXh0IERhdGEgRmlnIDVjCgpgYGB7cn0KcGxvdFN0YWNrZWRCYXJCeUdlbm8gPC0gZnVuY3Rpb24oZ2VuZSwgbGFiKSB7CiAgICBkYXQgPC0gRmV0Y2hEYXRhKFRCT19zZXVyYXQsIHZhcnMgPSBjKGdlbmUsICJHZW5vdHlwZSIpKQogICAgZGF0IDwtIGRhdCAlPiUKICAgICAgbXV0YXRlKEV4cHJlc3Npb25fU3RhdHVzID0gaWZlbHNlKGRhdFssZ2VuZV0gPiAwLjAxLCAiUG9zaXRpdmUiLCAiTmVnYXRpdmUiKSkKICAgIAogICAgeCA8LSB0YWJsZShkYXQkR2Vub3R5cGUsIGRhdCRFeHByZXNzaW9uX1N0YXR1cykKICAgIAogICAgcHJvcG9ydGlvbnMgPC0gYXMuZGF0YS5mcmFtZShwcm9wLnRhYmxlKHgsIG1hcmdpbiA9IDEpKQogICAgY29sbmFtZXMocHJvcG9ydGlvbnMpIDwtIGMoIkNsdXN0ZXIiLCAiU2FtcGxlIiwgIkZyYWN0aW9uIikKCiAgICBwIDwtIGdncGxvdChwcm9wb3J0aW9ucywgYWVzKGZpbGwgPSBTYW1wbGUsIHkgPSBGcmFjdGlvbiwgeCA9IENsdXN0ZXIpKSArIAogICAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgc3RhdCA9ICJpZGVudGl0eSIpCiAgICBwIDwtIHAgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYmx1ZTQiLCJyZWQzIikpKyB0aGVtZV9idygpICsgCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTIwKSwgCiAgICAgICAgICAgICAgYXhpcy50aXRsZS54ID1lbGVtZW50X3RleHQoc2l6ZT0yMCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgCiAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTApLCAKICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgZmFjZSA9ICJwbGFpbiIsIGhqdXN0ID0gMC41KSkgKyAKICAgICAgICBsYWJzKHkgPSBsYWIsIHggPSBOVUxMKQogICAgcmV0dXJuKHApCn0KYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90U3RhY2tlZEJhckJ5R2VubygiQXNjbDEiLCAiRnJhY3Rpb24gb2YgQXNjbDEtaGkgY2VsbHMgKD4wLjAxKSIpCnBsb3RTdGFja2VkQmFyQnlHZW5vKCJOZXVyb2QxIiwgIkZyYWN0aW9uIG9mIE5ldXJvZDEtaGkgY2VsbHMgKD4wLjAxKSIpCnBsb3RTdGFja2VkQmFyQnlHZW5vKCJQb3UyZjMiLCAiRnJhY3Rpb24gb2YgUG91MmYzLWhpIGNlbGxzICg+MC4wMSkiKQpgYGAKCiMjIyBFeHRlbmRlZCBEYXRhIEZpZy4gNWUKClZpb2xpbiBwbG90cyBvZiBleHByZXNzaW9uIG9mIFRGcyBieSBMZWlkZW4gY2x1c3RlcgoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdlbmVzIDwtIGMoIkFzY2wxIiwiTmV1cm9kMSIsIlBvdTJmMyIpCgojIENyZWF0ZSB2aW9saW4gcGxvdHMgd2l0aCBLcnVza2FsLVdhbGxpcyB0ZXN0CnBsb3RzIDwtIGxhcHBseShnZW5lcywgZnVuY3Rpb24oZ2VuZSkgewogIHAgPC0gVmxuUGxvdChUQk9fc2V1cmF0LAogICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmUsCiAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gImxlaWRlbl9zY1ZJXzEuMiIsCiAgICAgICAgICAgICAgIGNvbHMgPSBteV9jb2xvcnMsCiAgICAgICAgICAgICAgIGFscGhhID0gMC41KSArICAjIHNtYWxsZXIgZG90cwogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gImtydXNrYWwudGVzdCIsIAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gInAuZm9ybWF0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwueCA9IDIsc2l6ZSA9IDUpICsKICAgIGdndGl0bGUoIiIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiKSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAgIyBSZW1vdmUgbGVnZW5kCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArICAjIFJlbW92ZSB4LWF4aXMgbGFiZWwKICAgIGxhYnMoeSA9ICJFeHByZXNzaW9uIikgICMgQ2hhbmdlIHktYXhpcyBsYWJlbCB0byAiRXhwcmVzc2lvbiIKICByZXR1cm4ocCkKfSkKCiMgQXJyYW5nZSBwbG90cwpwYXRjaHdvcms6OndyYXBfcGxvdHMocGxvdHMsIG5jb2wgPSAzKQpgYGAKCiMjIyMgRXh0IERhdGEgRmlnIDEwCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIklvbm9fTW91c2VfRXh0MSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJJb25vX0h1bWFuMSIpLCBwdC5zaXplPTAuMiwKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKYGBgCgojIyMgRXh0IERhdGEgRmlnLiAxMGUgKHZpb2xpbiBwbG90cyBvZiBjb25zZW5zdXMgc2lnbmF0dXJlcyBieSBTQ0xDIGZhdGUpCgpgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJJb25vX01vdXNlX0V4dDEiLCB5bD1jKC0wLjEsIDAuNDUpKQpwbG90VmxuQnlQaGVuKCJJb25vX0h1bWFuMSIsIHlsPWMoLTAuMSwgLjc1KSkKYGBgCgojIyMjIEZpZyA1ZAoKQ2FyaXMgU0NMQyB0dW1vciBzaWduYXR1cmVzIGluIGJhc2FsIGNlbGxzCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjYXJpc19mZWF0IDwtICBjKCJDYXJpc19BMSIsIkNhcmlzX1kxIiwiQ2FyaXNfTjEiLCJDYXJpc19NaXhlZDEiLCJDYXJpc19QMSIsIkNhcmlzX1ROLTEiKQpsaWJyYXJ5KHZpcmlkaXMpCnYgPC0gRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjYXJpc19mZWF0LCBwdC5zaXplPTAuMiwgcmVkdWN0aW9uPSd1bWFwJykgCnYgPC0gbGFwcGx5KHYsIGArYCwgc2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb249InJvY2tldCIsIGRpcmVjdGlvbj0tMSkpCmxhcHBseSh2LCBgK2AsIE5vQXhlcygpKQpgYGAKCiMjIyMgRmlnIDVkICh2aW9saW4gcGxvdHMgb2YgaHVtYW4gdHVtb3IgU0NMQyBzY29yZXMgYnkgU0NMQyBmYXRlKQoKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9My41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJDYXJpc19BMSIsIHlsPWMoLTAuMSwgMC4yKSkKcGxvdFZsbkJ5UGhlbigiQ2FyaXNfWTEiLCB5bD1jKC0wLjEsIDAuMikpCnBsb3RWbG5CeVBoZW4oIkNhcmlzX04xIiwgeWw9YygtMC4xLCAwLjMpKQpwbG90VmxuQnlQaGVuKCJDYXJpc19NaXhlZDEiLCB5bD1jKC0wLjEsIDAuMTUpKQpwbG90VmxuQnlQaGVuKCJDYXJpc19QMSIsIHlsPWMoLTAuMSwgMC4yNSkpCnBsb3RWbG5CeVBoZW4oIkNhcmlzX1ROLjEiLCB5bD1jKC0wLjEsIDAuMjUpKQpgYGAKCiMjIyMgRmlnLiA1ZQoKR2VuZSBzaWduYXR1cmUgc2NvcmVzIGNvcnJlbGF0aW9uIGhlYXRtYXAKCmBgYHtyIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTl9CnNpZ25hdHVyZV9tYXRyaXggPC0gRmV0Y2hEYXRhKFRCT19zZXVyYXQsIHZhcnMgPSBjKCJDYXJpc19BMSIsICJHZW9yZ2VfQTEiLCAiTGl1X0ExIiwiTGlzc2FfQTEiLCJBU0NMMV9UYXJnZXRzMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYXJpc19OMSIsIkdlb3JnZV9OMSIsICJMaXVfTjEiLCJMaXNzYV9OMSIsICJORVVST0QxX1RhcmdldHMxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNhcmlzX1AxIiwiR2VvcmdlX1AxIiwgIkxpdV9QMSIsIlBPVTJGM19UYXJnZXRzMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYXJpc19ZMSIsIkdlb3JnZV9ZMSIsICJMaXNzYV9ZMSIsICJZQVBfQWN0aXZpdHkxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRfQ2VsbF9JbmZsYW1lZF9HYXkxIiwiTUhDX1NpZ19HYXkxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5FX0NvbnNlbnN1czEiLCJCYXNhbF9Db25zZW5zdXMxIiwiVHVmdF9Db25zZW5zdXMxIikpCgojIENvbXB1dGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBtYXRyaXgKY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcihzaWduYXR1cmVfbWF0cml4LCBtZXRob2QgPSAicGVhcnNvbiIpCgojIERlZmluZSBjb2xvciBzY2FsZSBmcm9tIC0xIHRvIDEKYnJlYWtzX3NlcSA8LSBzZXEoLTEsIDEsIGxlbmd0aC5vdXQgPSAxMDApICAjIEVuc3VyZSBzY2FsZSBjb3ZlcnMgZnVsbCBjb3JyZWxhdGlvbiByYW5nZQoKcGhlYXRtYXA6OnBoZWF0bWFwKGNvcnJlbGF0aW9uX21hdHJpeCwgCiAgICAgICAgIGNvbG9yID0gc2NpY286OnNjaWNvKDEwMCwgcGFsZXR0ZSA9ICJiZXJsaW4iKSwKICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gRkFMU0UsIAogICAgICAgICBicmVha3MgPSBicmVha3Nfc2VxLCBudW1iZXJfY29sb3IgPSAiZ3JheTgwIixmb250c2l6ZV9udW1iZXI9NiwKICAgICAgICAgbWFpbiA9ICJTaWduYXR1cmUgY29ycmVsYXRpb24gaW4gbW91c2UgVEJPIEFsbG9ncmFmdHMiLCBjbHVzdGVyX2NvbHMgPSBUUlVFLCBjbHVzdGVyX3Jvd3M9VFJVRSkKYGBgCgojIyMjIEZpZyA1ZwoKSW5mbGFtbWF0b3J5IHNpZ25hdHVyZXMgaW4gYmFzYWwgY2VsbHMKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgRmlnIDVnIGZlYXR1cmUgcGxvdCAoTUhDX1NpZ19HYXkxPSJBbnRpZ2VuIHByZXNlbnRhdGlvbiIpICMKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJNSENfU2lnX0dheTEiKSwgcHQuc2l6ZT0wLjIsIAogICAgICAgICAgICByZWR1Y3Rpb249J3VtYXAnKSArIHZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMob3B0aW9uPSJyb2NrZXQiLGRpcmVjdGlvbj0tMSkgJiBOb0F4ZXMoKQoKIyMjIE5NRjMtSSBzaWduYXR1cmUgZm9yIEZpZy4gNWcKRmVhdHVyZVBsb3QoVEJPX3NldXJhdCwgZmVhdHVyZXMgPSBjKCJOTUYzLUkxIiksIHB0LnNpemU9MC4yLCAKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKCiMjIyBHYXkgZXQgYWwgU0NMQy1JIHNpZ25hdHVyZSBmb3IgRmlnLiA1ZwpGZWF0dXJlUGxvdChUQk9fc2V1cmF0LCBmZWF0dXJlcyA9IGMoIkdheV9TQ0xDLUkxIiksIHB0LnNpemU9MC4yLCAKICAgICAgICAgICAgcmVkdWN0aW9uPSd1bWFwJykgKyB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKCmBgYAoKIyMjIyBGaWcgNWcgKHZpb2xpbiBwbG90cyBvZiBpbmZsYW1tYXRpb24gc2NvcmVzIGJ5IFNDTEMgZmF0ZSkKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTMuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiTUhDX1NpZ19HYXkxIiwgeWw9YygtMC4xLCAwLjgpKQpwbG90VmxuQnlQaGVuKCJOTUYzLkkxIiwgeWw9YygtMC4xLCAwLjUpKQpwbG90VmxuQnlQaGVuKCJHYXlfU0NMQy5JMSIsIHlsPWMoLTAuMSwgMC4zKSkKYGBgCgojIyMjIEZpZyA1aCAodmlvbGluIHBsb3RzIG9mIHRoZXJhcGV1dGljIHRhcmdldCBnZW5lIGV4cHJlc3Npb24gYnkgU0NMQyBmYXRlKQoKYGBge3IgZmlnLmhlaWdodD0yLjUsIGZpZy53aWR0aD04fQp4X2xhYnMgPC0gYygiQSIsIkEvTiIsIk4iLCJBdCIsIlAiLCJTTCIsIkIiKQoKdiA8LSBWbG5QbG90KFRCT19zZXVyYXQsIGZlYXR1cmVzID0gYygiRGxsMyIsICJOY2FtMSIsICJTZXo2IiwgIlRhY3N0ZDIiKSwgCiAgICAgICAgZ3JvdXAuYnk9YygiUGhlbm8iKSwgY29scz1waGVub19jb2wsYWxwaGE9MC4wNSwgbmNvbD00KQp2IDwtIGxhcHBseSh2LCAgYCtgLCBsYWJzKHg9TlVMTCwgeT0iRXhwcmVzc2lvbiIpKQp2IDwtIGxhcHBseSh2LCAgYCtgLCB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCkpKQp2IDwtIGxhcHBseSh2LCAgYCtgLCAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9eF9sYWJzKSkKCnBhdGNod29yazo6d3JhcF9wbG90cyh2LCBuY29sPTQpCmBgYAoKIyMjIyBFeHQgRGF0YSBGaWcgNmEKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9CkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J0dlbm9DVCcsIGNvbHM9bXlfY29sb3JzLCBzaHVmZmxlPVRSVUUsIAogICAgICAgIHJlZHVjdGlvbj0ndW1hcCcsIGxhYmVsPUZBTFNFLCBsYWJlbC5zaXplPTYpICYgTm9BeGVzKCkgKyBOb0xlZ2VuZCgpCkRpbVBsb3QoVEJPX3NldXJhdCwgZ3JvdXAuYnk9J0dlbm9DVCcsIGNvbHM9bXlfY29sb3JzLCBzaHVmZmxlPVRSVUUsIAogICAgICAgIHJlZHVjdGlvbj0nZmEnLCBsYWJlbD1GQUxTRSwgbGFiZWwuc2l6ZT02KSAmIE5vQXhlcygpICsgTm9MZWdlbmQoKQpgYGAKCiMjIyBDZWxsVGFnIGFuYWx5c2lzIGluIG90aGVyIG5vdGVib29rCg==